package isi.servlet;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Vector;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class Acquisti extends HttpServlet{

	static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
	static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema"; 
	static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
	
	private static final long serialVersionUID = 1L;
	@Override public void doPost(HttpServletRequest req, HttpServletResponse res){
		doGet(req,res);
	}
	
	@Override public void doGet(HttpServletRequest req, HttpServletResponse res){
		
		//Imposto il contentType della risposta
		res.setContentType("plain/text");
		
		//Prendo il Writer per scrivere la risposta
		PrintWriter out;
		try{
			out = res.getWriter();
		}
		catch(IOException ioe){
			try{
				res.sendError(500);
			}
			catch(IOException e){
				return;
			}
			return;
		}
		
		
		//Stampo i dati della richiesta
		printRequest(req,out);
		
		//abilito la sessione che tiene lo storico del parametro param
		//Stampo i dati relativi alla sessione
		session(req,out);
	}
	
	
	private void printRequest(HttpServletRequest req, PrintWriter out){
		
		//Stampo gli header http della richiesta
		
		out.write("====== Richiesta HTTP ======\n");
		Enumeration<?> headersName = req.getHeaderNames();
		while(headersName.hasMoreElements()){
			String header = (String) headersName.nextElement();
			out.write(header + ": " + req.getHeader(header) + "\n");
			System.out.println(header + ": " + req.getHeader(header) + "\n");
		}
		
	}
	
	private void session(HttpServletRequest req, PrintWriter out){
		out.write("======   Carrello  ======\n");
		//Recupero la lista di parametri in sessione o la instanzio se ancora non esiste
		HttpSession session = req.getSession();
		Carrello carrello = null;
		if(session.getAttribute("carrello") != null)
			carrello = (Carrello) (session.getAttribute("carrello"));
		else 
			carrello = new Carrello();
		//Aggiorno il carrello con il nuovo ordine
		updateCarrello(req, carrello);
	
		//Inserisco la lista dei parametri aggiornata in sessione.
		session.setAttribute("carrello", carrello);
		
		out.write(carrello.print());
	}
	
	private void updateCarrello(HttpServletRequest req, Carrello carrello){
		//Costruisco il DOM dell'ordine
		Document doc = null;
		try{
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			
			File file = new File(getServletContext().getRealPath("ordine.xsd"));
			factory.setIgnoringElementContentWhitespace(true);
			factory.setNamespaceAware(true);
			factory.setValidating(true);
			factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
			factory.setAttribute(JAXP_SCHEMA_SOURCE, file);
			
			DocumentBuilder parser = factory.newDocumentBuilder();
			
			doc = parser.parse(req.getInputStream());
		}
		catch(Exception e){
			e.printStackTrace();
		}
		//Cerco gli articoli nell'ordine e li aggiungo al carrello.
		NodeList articoli = doc.getElementsByTagName("ns:articolo");
		
		for(int i = 0; i < articoli.getLength(); i++){
			Element articoloElement = (Element) articoli.item(i);
			Articolo articolo = new Articolo(articoloElement.getFirstChild().getTextContent(), Integer.parseInt(articoloElement.getLastChild().getTextContent()));
			System.out.println("Controllo il saldo");
			if(checkSaldo(carrello.count() + articolo.quantita)){
				carrello.add(articolo);
			}
		}
	}
	
	public boolean checkSaldo(int count){
		SOAPMessage request,response = null;
		int saldo = 0;
		try{
			MessageFactory mf = MessageFactory.newInstance();
			//Costruiamo il SOAPMessage vuoto
			request = mf.createMessage();
			//Popoliamo il body del SOAPMessage con i nodi necessari
			SOAPBodyElement saldoEle = request.getSOAPBody().addBodyElement(new QName("http://www.bank.org/ns", "saldo", "bns"));
			saldoEle.addChildElement(new QName("http://www.bank.org/ns", "account", "bns")).setValue("1234567ABCD");
			
			SOAPConnection conn = SOAPConnectionFactory.newInstance().createConnection();
			response = conn.call(request, "http://localhost:8081/bank/sportello/");
			SOAPBody body =	response.getSOAPBody();
			Node saldoNode = body.getFirstChild().getFirstChild();
			saldo = Integer.parseInt(saldoNode.getTextContent());
			
		}
		catch(SOAPException e){
			e.printStackTrace();
			return false;
		}
		System.out.println("Saldo:" + saldo + " Carrello:" + count);
		return saldo>=count;
	}
	
	
	public class Carrello{
		Vector<Articolo> articoli;
		
		public Carrello(){ 
			articoli = new Vector<Articolo>();
		}
		
		public void add(Articolo a){
			articoli.add(a);
		}
		
		public int count(){
			int count=0;
			for(int i = 0; i<articoli.size(); i++){
				Articolo articolo = articoli.get(i);
				count += articolo.quantita;
			}
			return count;
		}
		
		public String print(){
			String txt = "";
			for(int i = 0; i<articoli.size(); i++){
				Articolo articolo = articoli.get(i);
				txt += articolo.nome + " x " + articolo.quantita + "\n";
			}
			return txt;
		}
		
	}
	
	
	public class Articolo{
		String nome;
		int quantita;
		public Articolo(String nome, int quantita){
			this.nome = nome;
			this.quantita = quantita;
		}
	}
}

